package bloggo

import (
	"errors"
	"github.com/gomodule/redigo/redis"
	"strconv"
)

const (
	// CODE_EXPIRE_TIME 验证码过期时间
	CODE_EXPIRE_TIME = 15 * 60

	// USER_CODE_KEY 验证码
	USER_CODE_KEY = "code:"

	// BLOG_VIEWS_COUNT 博客浏览量
	BLOG_VIEWS_COUNT = "blog_views_count"

	// ARTICLE_VIEWS_COUNT 文章浏览量
	ARTICLE_VIEWS_COUNT = "article_views_count"

	// ARTICLE_LIKE_COUNT 文章点赞量
	ARTICLE_LIKE_COUNT = "article_like_count"

	// ARTICLE_USER_LIKE 用户点赞文章
	ARTICLE_USER_LIKE = "article_user_like:"

	// COMMENT_LIKE_COUNT 评论点赞量
	COMMENT_LIKE_COUNT = "comment_like_count"

	// COMMENT_USER_LIKE 用户点赞评论
	COMMENT_USER_LIKE = "comment_user_like:"

	// WEBSITE_CONFIG 网站配置
	WEBSITE_CONFIG = "website_config"

	// USER_AREA 用户地区
	USER_AREA = "user_area"

	// VISITOR_AREA 访客地区
	VISITOR_AREA = "visitor_area"

	// PAGE_COVER 页面封面
	PAGE_COVER = "page_cover"

	// ABOUT 关于我信息
	ABOUT = "about"

	// UNIQUE_VISITOR 访客
	UNIQUE_VISITOR = "unique_visitor"

	// ARTICLE_SET 浏览文章集合
	ARTICLE_SET = "articleSet"
)

func BytessConvToInt(d [][]byte) []int {
	var rd []int
	if len(d) <= 0 {
		return rd
	}
	for i := range d {
		temp, _ := strconv.Atoi(string(d[i]))
		rd = append(rd, temp)
	}
	return rd
}

func BytessConvToString(d [][]byte) []string {
	var rd []string
	if len(d) <= 0 {
		return rd
	}
	for i := range d {
		rd = append(rd, string(d[i]))
	}
	return rd
}

func Get(key string) ([]byte, error) {
	if key == "" {
		return nil, nil
	}
	c := redisClient.Get()

	return redis.Bytes(c.Do("GET", key))
}

// Incrby key增量 increment
func Incrby(key string, increment int) int {
	if key == "" {
		return 0
	}
	c := redisClient.Get()

	count, err := redis.Int(c.Do("INCRBY", key, increment))
	if err != nil {
		return 0
	}
	return count
}

func Set(key string, val []byte) bool {
	if key == "" {
		return false
	}
	//拿到一个连接
	c := redisClient.Get()

	_, err := c.Do("SET", key, val)
	if err != nil {
		return false
	}
	return true
}

// Setex set一个有过期时间的key和val
func Setex(key string, val []byte, seconds int) bool {
	if key == "" {
		return false
	}
	//拿到一个连接
	c := redisClient.Get()

	_, err := c.Do("SET", key, val, "EX", seconds)
	if err != nil {
		return false
	}
	return true
}

// Setnxex set一个有过期时间的key和val,并且是不存在的key
func Setnxex(key string, val []byte, seconds int) bool {
	if key == "" {
		return false
	}
	//拿到一个连接
	c := redisClient.Get()

	do, err := redis.Bytes(c.Do("SET", key, val, "NX", "EX", seconds))
	if err != nil {
		return false
	}
	if string(do) == "OK" {
		return true
	}
	return true
}

// Expire 为key添加过期时间
func Expire(key string, seconds int) bool {
	if key == "" {
		return false
	}
	//拿到一个连接
	c := redisClient.Get()

	_, err := c.Do("EXPIRE", key, seconds)
	if err != nil {
		return false
	}
	return true
}

func Del(key string) bool {
	if key == "" {
		return false
	}
	c := redisClient.Get()

	_, err := c.Do("DEL", key)
	if err != nil {
		return false
	}
	return true
}

// SisMember set中是否存在member成员
func SisMember(key string, member []byte) bool {
	if key == "" {
		return false
	}
	c := redisClient.Get()

	count, err := redis.Int(c.Do("SISMEMBER", key, member))
	if err != nil {
		return false
	}
	return count > 0
}

// Smembers 获取set中所有member成员
func Smembers(key string) [][]byte {
	if key == "" {
		return nil
	}
	c := redisClient.Get()

	data, err := redis.ByteSlices(c.Do("SMEMBERS", key))
	if err != nil {
		return nil
	}
	return data
}

// Sadd 向set中添加一个memberc成员
func Sadd(key string, member []byte) bool {
	if key == "" {
		return false
	}
	c := redisClient.Get()

	count, err := redis.Int(c.Do("SADD", key, member))
	if err != nil {
		return false
	}
	return count > 0
}

// Srem 从set中移除一个memberc成员
func Srem(key string, member []byte) bool {
	if key == "" {
		return false
	}
	c := redisClient.Get()

	count, err := redis.Int(c.Do("SREM", key, member))
	if err != nil {
		return false
	}
	return count > 0
}

// Hincrby 将哈希表 key 中域 field 的值 增加 delta
func Hincrby(key string, field []byte, delta int) int {
	if key == "" {
		return 0
	}
	c := redisClient.Get()

	count, err := redis.Int(c.Do("HINCRBY", key, field, delta))
	if err != nil {
		return 0
	}
	return count
}

// Hget 获取将哈希表 key 中域 field 的值
func Hget(key string, field []byte) ([]byte, error) {
	if key == "" {
		return nil, errors.New("key is empty")
	}
	c := redisClient.Get()

	return redis.Bytes(c.Do("HGET", key, field))
}

// Hkeys 获取将哈希表 key 中 所有 field
func Hkeys(key string) ([]byte, error) {
	if key == "" {
		return nil, errors.New("key is empty")
	}
	c := redisClient.Get()

	return redis.Bytes(c.Do("HKEYS", key))
}

// Hgetall 获取将哈希表 key 中 所有 field 和值
func Hgetall(key string) (map[string][]byte, error) {
	if key == "" {
		return nil, errors.New("key is empty")
	}

	c := redisClient.Get()
	slices, err := redis.ByteSlices(c.Do("HGETALL", key))
	if err != nil {
		return nil, err
	}

	data := make(map[string][]byte)
	l := len(slices)
	for i := 0; i < l; i += 2 {
		data[string(slices[i])] = slices[i+1]
	}

	return data, nil
}

// Zscore 获取key cursor排序值
func Zscore(key string, cursor []byte) float64 {
	if key == "" {
		return 0
	}
	c := redisClient.Get()

	float, err := redis.Float64(redis.Bytes(c.Do("ZSCORE", key, cursor)))
	if err != nil {
		return 0
	}
	return float
}

// Zincrby 增加成员排序值increment
func Zincrby(key string, increment float64, member []byte) float64 {
	if key == "" || member == nil {
		return 0
	}
	c := redisClient.Get()

	float, err := redis.Float64(redis.Bytes(c.Do("ZINCRBY", key, increment, member)))
	if err != nil {
		return 0
	}
	return float
}

// Zrevrank 返回当前成员在key中的排名（从大到小） -1表示不存在
func Zrevrank(key string, member []byte) int {
	if key == "" {
		return -1
	}
	c := redisClient.Get()

	count, err := redis.Int(c.Do("ZREVRANK", key, member))
	if err != nil {
		return -1
	}
	return count
}

// Zrank 返回当前成员在key中的排名（从小到大） -1表示不存在
func Zrank(key string, member []byte) int {
	if key == "" {
		return -1
	}
	c := redisClient.Get()

	count, err := redis.Int(c.Do("ZRANK", key, member))
	if err != nil {
		return -1
	}
	return count
}

// Zrevrange 返回当前成员在key中的指定范围排名（从大到小）
func Zrevrange(key string, start, stop int) [][]byte {
	if key == "" {
		return nil
	}
	c := redisClient.Get()

	slices, err := redis.ByteSlices(c.Do("ZREVRANGE", key, start, stop))
	if err != nil {
		return nil
	}
	return slices
}

// Zrange 返回当前成员在key中的指定范围排名（从小到大）
func Zrange(key string, start, stop int) [][]byte {
	if key == "" {
		return nil
	}
	c := redisClient.Get()

	slices, err := redis.ByteSlices(c.Do("ZRANGE", key, start, stop))
	if err != nil {
		return nil
	}
	return slices
}

// Zrem 移除指定成员member
func Zrem(key string, member []byte) bool {
	if key == "" {
		return false
	}
	c := redisClient.Get()

	_, err := c.Do("ZREM", key, member)
	if err != nil {
		return false
	}
	return true
}
